package com.wgt.startx.helper;

import com.wgt.startx.annotation.Autowire;
import com.wgt.startx.util.CollectionUtils;
import org.apache.commons.beanutils.PropertyUtils;

import java.lang.reflect.Field;
import java.util.Map;

/**
 *
 * 我们实现实例化 Controller/Service 的实例,去实例化它们里面成员变量
 * 不是用开发者用new来实例，而是要框架自身去实例化它们，想这样的类实例化过程，称为IOC（invoersion ofControl），
 * 控制不是有开发者决定，而是反转给框架了，也将控制反转称为DI（Dependency Injection,依赖注入）。
 *
 *
 * 思路：
 *  先通过BeanHelper 获取所有BeanMap（一个map<Class<?>,Object>结构，记录类与对象的映射关系）。
 *  然后遍历这个映射关系，分别取出Bean类和Bean实例，进而通过反射获取类中所有的成员变量。
 *  继续遍历这些成员变量，在循环中判断当前成员变量是否带有@Autowire注解，若带有着给他赋值
 * Created by wgt on 2017/7/30.
 */


public final class IOCHelper {
    static {
        Map<Class<?>,Object> beanMap = BeanHelper.getBeanMap();
        System.out.println("beanMap: "+beanMap);
        if (CollectionUtils.isNotEmpty(beanMap)){
            for (Map.Entry<Class<?>,Object> entry:beanMap.entrySet()){
                Class beanClass = entry.getKey();
                Object instance = entry.getValue();
                Field[] fields = beanClass.getDeclaredFields();
                System.out.println("current class is: "+beanClass+" , fields length is:"+fields.length);
                if (CollectionUtils.isNotEmpty(fields)){
                    for (Field field:fields){
                        System.out.println("field: "+field);
                        if (field.isAnnotationPresent(Autowire.class)){
                            Class<?> cls = field.getType();
                            Object fieldInstance = beanMap.get(cls);
                            System.out.println("cls: "+cls);
                            System.out.println("fieldInstnce: "+fieldInstance);
                            if (fieldInstance!=null){
                                try {
                                    PropertyUtils.setProperty(instance,field.getName(),fieldInstance);
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                                //ReflectionUtil.setField(instance,field,fieldInstance);
                            }
                        }
                    }
                }
            }
        }
    }
}
